#ifndef HASHTABLE_H
#define HASHTABLE_H

typedef void * hashtable_t;
typedef void * hashiter_t;

/* returns a new hash table 
 * initial_len - the initial size of the hash table
 * growth_factor - the multiple of size to grow the hash table when full
 * hash_cb - hashes a record
 * cmp_cb - compares two records (returns 0 if equal)
 */
void * hashtable_alloc(int initial_len, double growth_factor,
                       unsigned long (*hash_cb)(void *),
                       int (*cmp_cb)(void *, void *));

/* frees the memory for the hash table */
void hashtable_free(void * table);

/* returns 1 if the key already exists */
int hashtable_insert(void * table, void * record);

/* returns the record or NULL */
void * hashtable_find(void * table, void * record);

/* returns the record or NULL if not found */
void * hashtable_delete(void * table, void * record);

/* starts an iterator over the hash table, the elements can't be modified */
hashiter_t hashtable_itr_start(void * table);

/* returns the next record from the iterator */
void * hashtable_itr_next(hashiter_t iterator);

/* end the iteration, the elements can now be modified */
void hashtable_itr_end(hashiter_t iterator);

/* helper functions */


/* 
   hash a string:
   str - string to be hashed
   lasthash - 0 if this is the first hash otherwise the previous hash value
              to be combined into this
*/
/* hash function recommended by Ozan Yigit 
 http://www.cs.yorku.ca/~oz/hash.html
 "this algorithm (k=33) was first reported by dan bernstein"
*/
unsigned long hashtable_djb2(unsigned char *str, unsigned long lasthash);

#endif /* HASHTABLE_H */
